﻿using System;
using System.Linq;
using System.Linq.Expressions;

namespace TSharp.Core.Repository
{
    /// <summary>
    /// 执行批量更新、删除操作接口
    /// </summary>
    public interface IBatchUnitOfWork
    {
        /// <summary>
        /// 批量删除（不需要Commit操作，批量执行后即刻提交事务）
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="deleteWhere">删除的查询条件，所能查到的对象将被删除.</param>
        /// <returns>System.Int32.</returns>
        int Delete<TEntity>(IQueryable<TEntity> deleteWhere) where TEntity : class;

        /// <summary>
        /// 批量删除（不需要Commit操作，批量执行后即刻提交事务）
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="filterExpression">删除的查询条件，所能查到的对象将被删除。</param>
        /// <returns>System.Int32.</returns>
        int Delete<TEntity>(Expression<Func<TEntity, bool>> filterExpression) where TEntity : class;

        /// <summary>
        /// 批量更新（不需要Commit操作，批量执行后即刻提交事务）
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="filterExpression">更新的查询条件，所能查到的对象将被更新。</param>
        /// <param name="updateExpression">对每一条数据进行更新的字段。</param>
        /// <returns>System.Int32.</returns>
        int Update<TEntity>(Expression<Func<TEntity, bool>> filterExpression,
          Expression<Func<TEntity, TEntity>> updateExpression)
          where TEntity : class;

        /// <summary>
        /// 批量更新（不需要Commit操作，批量执行后即刻提交事务）
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="updateWhere">更新的查询条件，所能查到的对象将被更新.</param>
        /// <param name="updateExpression">对每一条数据进行更新的字段。</param>
        /// <returns>System.Int32.</returns>
        int Update<TEntity>(IQueryable<TEntity> updateWhere,
           Expression<Func<TEntity, TEntity>> updateExpression)
       where TEntity : class;

    }
    /// <summary>
    /// 可被缓存的工作单元，由系统自动释放，不需要编码进行释放
    /// </summary>
    public interface IUnitOfWork : ISql, IDisposable
    {
        /// <summary>
        /// 获取批量操作接口
        /// </summary>
        /// <returns>IBatchUnitOfWork.</returns>
        IBatchUnitOfWork GetBatchUnitOfWork();

        /// <summary>
        /// Flushes content of unit of work to the underlying data storage. Causes unsaved
        /// entities to be written to the data storage.
        /// </summary>
        int Commit();

        /// <summary>
        /// 开启一个事务，可在不同上下文中进行代码同步，但需要数据库开启分布式事务服务
        /// </summary>
        ITransaction BeginTransaction();

        /// <summary>
        /// Ends transaction.
        /// Note: suggested pattern to manage a transaction is via *using* construct.
        /// You should set input param to null after calling the method.
        /// </summary>
        /// <example>
        /// using ( var tnx = uow.BeginTransaction() ) { /* do some work */ }
        /// </example>
        /// See also <seealso cref="ITransaction"/> interface for more details.
        void EndTransaction(ITransaction transaction);

        /// <summary>
        /// 插入一个数据实体到上下文，将在Commit()时保存导数据
        /// </summary>
        TEntity Insert<TEntity>(TEntity entity) where TEntity : class;

        /// <summary>
        /// 这是一个什么都没做的方法，将被BeginUpdate() 替代
        /// </summary>
        TEntity Update<TEntity>(TEntity entity) where TEntity : class;
        /// <summary>
        /// 开始更新一个实体，doUpdate()中将具体更新该实体
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="originEntity">The entity.</param>
        /// <param name="doUpdate">The do update.</param>
        /// <returns>``0.</returns>
        TEntity Update<TEntity>(TEntity originEntity, Action<TEntity> doUpdate) where TEntity : class;
        /// <summary>
        /// 将该实体附加到上下文，并开始更新
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="originEntity">The origin entity.</param>
        /// <returns>``0.</returns>
        TEntity BeginUpdate<TEntity>(TEntity originEntity) where TEntity : class;
        /// <summary>
        /// 将一个实体标记为删除（实现了软删除接口的将进行软删除）
        /// </summary>
        TEntity Delete<TEntity>(TEntity entity) where TEntity : class;
        /// <summary>
        /// 将一个实体标记为删除（忽略软删除标记）
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns>``0.</returns>
        TEntity RealDelete<TEntity>(TEntity entity) where TEntity : class;
        /// <summary>
        /// 根据表达式查询，如果工作单元为只读状态，则返回一个只读查询
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <param name="predicate">The predicate.</param>
        /// <returns>``0.</returns>
        IQueryable<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class;
        /// <summary>
        /// 根据表达式查询，如果工作单元为只读状态，则返回一个只读查询
        /// </summary>
        /// <typeparam name="TEntity">The type of the T entity.</typeparam>
        /// <returns>IQueryable{``0}.</returns>
        IQueryable<TEntity> Find<TEntity>() where TEntity : class;
        /// <summary>
        /// 根据主键查询，如果工作单元为只读状态，则返回一个只读查询
        /// </summary>
        TEntity GetById<TEntity>(params object[] ids) where TEntity : class;
    }
}
